<template>
    <span class="evidence-editor">
        <el-dialog :title="title"
                   :visible="true"
                   :modal="editorModal"
                   :lock-scroll="true"
                   :width="'70%'"
                   :class="'small-dialog'"
                   :fullscreen="true"
                   :before-close="() => onCancelDialog()">
            <div class="dialog-content">
                <el-row :gutter="20">
                    <el-col :span="4"
                            class="left-image-side">
                        <div class="grid-content bg-purple">
                            <el-upload v-if="editorMode === 'edit'"
                                       class="upload-demo res-view"
                                       drag
                                       multiple
                                       :action="`/api/file/upload?purpose=${fileParams.purpose}&ownerId=${fileParams.ownerId}`"
                                       :show-file-list="false"
                                       :before-upload="imageBeforeUpload"
                                       :on-success="imageUploadSuccess">
                                <i class="el-icon-upload"></i>
                                <div class="el-upload__text">将文件拖到此处, </div>
                                <div class="el-upload__text">或
                                    <em>点击上传</em>
                                </div>
                            </el-upload>
                            <div :class="{ 'image-list': true, 'image-list-exam': editorMode === 'exam'}">
                                <div class="no-image-item"
                                     v-if="!evidenceImages || evidenceImages.length === 0">
                                    <i class="no-img el-icon-picture-outline" />
                                    <div>无资源</div>
                                </div>
                                <div v-for="image in evidenceImages"
                                     :key="image.id"
                                     :class="{
                                            'image-item-edit': editorMode === 'edit',
                                            'image-item': true,
                                            'image-item-active': isImageActive(image)
                                          }">
                                    <i v-if="editorMode !== 'edit' && isImageActive(image)"
                                       class="image-checked el-icon-circle-check" />
                                    <i v-if="editorMode === 'edit' && isImageActive(image)"
                                       class="image-remove el-icon-circle-close"
                                       @click="() => removeImage(image.id)" />
                                    <el-tooltip effect="dark"
                                                placement="top"
                                                :content="image.name ? image.name : image.originFileName">
                                        <img :src="`/api/${image.fileUrl}`"
                                             @click="() => selectImage(image)"
                                             width="100%"
                                             height=100 />
                                    </el-tooltip>
                                </div>
                            </div>
                        </div>
                    </el-col>
                    <el-col :span="16"
                            :class="editorAction !== 'view' && editorAction !== 'select' && editorAction !== 'confirm'
                                 ? 'center-content' : 'center-content-readonly'">
                        <div class="grid-content bg-purple">
                            <drop class="drop"
                                  id="currentImageId"
                                  :class="{ dropOver }"
                                  @dragover="dropOver = true"
                                  @dragleave="dropOver = false"
                                  @drop="handleDrop">
                                <img v-if="currentImage"
                                     :src="`/api/${currentImage.fileUrl}`"
                                     width="100%"
                                     @load="imageLoaded" />
                                <VueDragResize v-if="usingStampImages && isValidImageSize(stampImage) && (mode === 'edit' || editorAction === 'stamp')"
                                               v-for="stampImage in usingStampImages"
                                               :imagekey="stampImage.key"
                                               :imageid="stampImage.id"
                                               :class="{ 'exam-area': editorMode === 'exam'}"
                                               :key="stampImage.key"
                                               :isActive="currentStamp && currentStamp.key === stampImage.key"
                                               :isDraggable="editorMode === 'edit'"
                                               :isResizable="editorMode === 'edit'"
                                               :w="stampImage.scaleW * imageWidth"
                                               :h="stampImage.scaleH * imageHeight"
                                               :x="stampImage.scaleX * imageWidth"
                                               :y="stampImage.scaleY * imageHeight"
                                               :parentW="imageWidth"
                                               :parentH="imageHeight"
                                               :parentLimitation="true"
                                               v-on:activated="e => setActive(stampImage, true)"
                                               v-on:dragging="changePosition($event, stampImage)"
                                               v-on:resizing="changeSize($event, stampImage)">
                                    <img v-if="examUsingStampImages[currentImage.id][stampImage.key] || editorMode === 'edit'"
                                         :src="`/api${stampImage.fileUrl}`"
                                         height="100%"
                                         width="100%" />
                                </VueDragResize>
                            </drop>
                        </div>
                    </el-col>
                    <el-col :span="4"
                            class="right-image-side"
                            v-if="editorAction !== 'view' && editorAction !== 'select' && editorAction !== 'confirm'">
                        <div class="grid-content bg-purple">
                            <el-select v-if="editorMode === 'edit'"
                                       class="res-view"
                                       v-model="imageListName"
                                       placeholder="请选择"
                                       @change="imageListNameSelect">
                                <el-option label="正在使用的资源"
                                           value="usingResources" />
                                <el-option label="备选资源"
                                           value="backupResources" />
                                <el-option label="位置尺寸配置"
                                           value="positionSizeConfig" />
                            </el-select>
                            <div class="res-view"
                                 v-if="editorMode === 'edit' && imageListName === 'backupResources'">
                                <el-cascader :clearable="true"
                                             :show-all-levels="false"
                                             :options="mediaClasses"
                                             :props="{ value: 'id', label: 'name', children: 'subClasses' }"
                                             @change="changeBackupResourcesClass"
                                             v-model="classIds"
                                             placeholder="请选择图分类" />
                            </div>
                            <div :class="{ 'image-list': true, 'image-list-exam': editorMode === 'exam'}">
                                <div class="no-image-item"
                                     v-if="imageListName === 'usingResources' && (!usingImageResources || usingImageResources.length === 0)">
                                    <i class="no-img el-icon-picture-outline" />
                                    <div>无资源</div>
                                </div>
                                <div v-if="imageListName === 'usingResources' && usingImageResources"
                                     v-for="image in usingImageResources"
                                     :key="image.id"
                                     class="image-item">
                                    <el-tooltip effect="dark"
                                                placement="top"
                                                :content="image.name ? image.name : image.originFileName">
                                        <drag class="drag"
                                              :transfer-data="image"
                                              :effect-allowed="['copy']"
                                              drop-effect="copy">
                                            <img :src="`/api${image.fileUrl}`"
                                                 height="100%" />
                                        </drag>
                                    </el-tooltip>
                                </div>
                                <div class="no-image-item"
                                     v-if="editorMode === 'edit' && imageListName === 'backupResources' && (!materialImages || materialImages.length === 0)">
                                    <i class="no-img el-icon-picture-outline" />
                                    <div>无资源</div>
                                </div>
                                <div v-if="editorMode === 'edit' && imageListName === 'backupResources' && materialImages && materialImages.length"
                                     v-for="image in materialImages"
                                     :key="image.id"
                                     class="image-item">
                                    <el-tooltip effect="dark"
                                                placement="top"
                                                :content="image.name ? image.name : image.originFileName">
                                        <drag class="drag"
                                              :transfer-data="image"
                                              :effect-allowed="['copy']"
                                              drop-effect="copy">
                                            <img :src="`/api${image.fileUrl}`"
                                                 height="100%" />
                                        </drag>
                                    </el-tooltip>
                                </div>
                                <div v-if="editorMode === 'edit' && imageListName === 'positionSizeConfig'">
                                    <div class="res-view">
                                        <div class="toolbar-input-suffix">
                                            X坐标：
                                            <el-input v-model="currentStampX"
                                                      @change="x => changePosition({left: x, top: currentStampY}, currentStamp)" />
                                        </div>
                                        <div class="toolbar-input-suffix">
                                            Y坐标：
                                            <el-input v-model="currentStampY"
                                                      @change="y => changePosition({left: currentStampX, top: y}, currentStamp)" />
                                        </div>
                                        <div class="toolbar-input-suffix">
                                            宽：
                                            <el-input v-model="currentStampW"
                                                      @change="w => changeSize({width: w, height: currentStampH}, currentStamp)" />
                                        </div>
                                        <div class="toolbar-input-suffix">
                                            高：
                                            <el-input v-model="currentStampH"
                                                      @change="h => changeSize({width: currentStampW, height: h}, currentStamp)" />
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </el-col>
                </el-row>
            </div>
            <div class="dialog-footer">
                <el-button @click="onCancelDialog">关闭</el-button>
                <el-button type="primary"
                           @click="onConfirmDialog">{{editorMode === 'edit' ? '保存' : '确定'}}</el-button>
            </div>
        </el-dialog>
    </span>
</template>

<script>
    /**
     * 凭证细节配置
     */
    import Vue from 'vue'
    import { mapGetters, mapActions, mapMutations } from 'vuex'
    import { MessageBox } from 'element-ui'
    import VueDragResize from 'vue-drag-resize'
    import { Drag, Drop } from 'vue-drag-drop'
    import consts from '@/const'
    import dialogEx from '@/components/dialog/dialogEx'
    import pageConfig from '../config'

    export default {
        name: 'evidenceEditor',
        props: ['mode', 'title', 'name', 'action', 'modal', 'form', 'init'],
        components: {
            VueDragResize,
            Drag,
            Drop
        },
        data() {
            return {
                editorModal: !!this.modal,
                editorMode: this.mode,
                // 业务action：view=true, confirm=true, select="2,3,4", stamp=true
                editorAction: this.action,
                stampsArea: true,
                classIds: null,
                currentImage: null,
                dropOver: false,
                imageLoading: true,
                imageHeight: 0,
                imageWidth: 0,
                operations: {},
                currentStampX: 0,
                currentStampY: 0,
                currentStampW: 0,
                currentStampH: 0,
                currentStamp: null,
                // 多选标记
                multipleSelected: {},
                formActions: this.form && this.form.actions ? this.form.actions : {},
                fileParams: { purpose: 'evid', ownerId: this.init ? this.init.id : null },
                // 右侧边栏视图名称
                imageListName: this.mode === 'edit' ? 'backupResources' : 'usingResources',
                // 当前凭证图加盖图章或签名列表
                usingStampImages: [],
                // 学员的盖章或签名记录map
                examUsingStampImages: {},
                // 当前凭证的表格底图和使用的图章或签名信息
                evidenStampImages: this.init && this.init.content ? JSON.parse(this.init.content) : {}
            }
        },
        mounted() {
            let self = this
            window.addEventListener('resize', () => {
                Vue.set(this, 'imageLoading', true)
                setTimeout(this.updateImageSize, 100)
            })
            this.getMediaClasses()
            this.getEvidenceImages(this.fileParams.ownerId)
            this.setMaterialImages({ content: null })
            if (!this.init.content) {
                this.getEvidence({
                    id: this.init.id,
                    cb: currentEvidence => {
                        this.evidenStampImages = currentEvidence.content
                            ? JSON.parse(currentEvidence.content)
                            : {}
                        this.initEvidenceStampedImages()
                    }
                })
            } else {
                this.initEvidenceStampedImages()
            }
        },
        computed: {
            ...mapGetters(['evidenceImages', 'mediaClasses', 'materialImages']),
            usingImageResources() {
                // 获取使用的图章或签名
                if (this.evidenStampImages) {
                    let map = {}
                    let keys = Object.keys(this.evidenStampImages)
                    let usingStamps = []
                    for (let key of keys) {
                        let stamps = this.evidenStampImages[key].stamps
                        usingStamps = usingStamps.concat(
                            stamps
                                ? stamps.filter(stamp => {
                                      if (map[stamp.id]) return false
                                      map[stamp.id] = true
                                      return true
                                  })
                                : []
                        )
                    }
                    return usingStamps
                }
                return null
            }
        },
        methods: {
            ...mapActions([
                'getMediaClasses',
                'getEvidenceImages',
                'removeEvidenceImage',
                'getMaterialImages',
                'getEvidence',
                'saveEvidence'
            ]),
            ...mapMutations(['setMaterialImages']),
            initEvidenceStampedImages() {
                const evidenceImages = this.evidenceImages
                this.examUsingStampImages = {}
                for (const evidenceImage of evidenceImages) {
                    if (
                        !this.examUsingStampImages[evidenceImage.id] &&
                        this.evidenStampImages[evidenceImage.id] &&
                        this.evidenStampImages[evidenceImage.id].stamps
                    ) {
                        this.examUsingStampImages[evidenceImage.id] = {}
                    }
                }
            },
            isValidImageSize(image) {
                return (
                    !this.imageLoading &&
                    this.imageWidth > 0 &&
                    this.imageHeight > 0 &&
                    image.scaleW &&
                    image.scaleH &&
                    image.scaleX &&
                    image.scaleY
                )
            },
            isImageActive(image) {
                const active =
                    (this.currentImage &&
                        this.editorMode === 'edit' &&
                        this.currentImage.id === image.id) ||
                    (this.currentImage &&
                        (this.editorAction === 'select' || this.editorAction === 'confirm') &&
                        this.multipleSelected[image.id])
                console.log('isImageActive', active)
                return active
            },
            onConfirmDialog() {
                if (this.editorMode === 'edit') {
                    this.saveEvidence({
                        id: this.fileParams.ownerId,
                        content: JSON.stringify(this.evidenStampImages)
                    })
                } else if (
                    this.editorMode === 'exam' &&
                    (this.editorAction === 'view' ||
                        this.editorAction === 'confirm' ||
                        this.editorAction === 'stamp' ||
                        this.editorAction === 'select')
                ) {
                    const {
                        examMissedClickResult,
                        examMissedStampResult,
                        multipleSelectedInOrder
                    } = this.processExamResult()
                    if (this.formActions.confirm) {
                        let result
                        if (this.editorAction === 'view') result = true
                        else if (this.editorAction === 'confirm')
                            result = examMissedClickResult.length === 0
                        else if (this.editorAction === 'stamp')
                            result = examMissedStampResult.length === 0
                        else if (this.editorAction === 'select')
                            result = multipleSelectedInOrder
                        // 回调confirm传递结果
                        console.log(
                            'onConfirmDialog::',
                            'mode=',
                            this.editorMode,
                            'action=',
                            this.editorAction,
                            'result=',
                            result
                        )
                        this.formActions.confirm(result, this.editorAction)
                    }
                } else if (this.formActions.confirm) {
                    this.formActions.confirm()
                }
            },
            processExamResult() {
                const evidenceImages = this.evidenceImages
                const examUsingStampImages = this.examUsingStampImages
                let examMissedClickResult = []
                let examMissedStampResult = []
                let examSelectResult = []
                // 处理盖章签名检查
                for (const evidenceImage of evidenceImages) {
                    const examUsingStampImage = examUsingStampImages[evidenceImage.id]
                    if (examUsingStampImage) {
                        // 该凭证表已被浏览, 检查是否有是否需要加盖凭证图章或签名
                        const evidenStamps = this.evidenStampImages[evidenceImage.id]
                            ? this.evidenStampImages[evidenceImage.id].stamps
                            : []
                        for (const evidenStamp of evidenStamps) {
                            if (!examUsingStampImage[evidenStamp.key]) {
                                // 该凭证表已被浏览，图章位置缺失
                                console.log('该凭证表已被浏览，图章位置缺失', evidenStamp.key)
                                examMissedStampResult.push(evidenStamp)
                            } else {
                                // 该凭证表已被浏览，图章位置正确
                                console.log('该凭证表已被浏览，图章位置正确', evidenStamp.key)
                            }
                        }
                    } else {
                        // 该凭证表未被浏览
                        examMissedClickResult.push(evidenceImage)
                    }
                }
                // 处理多选打印
                const multipleSelectedInOrder = this.getSelectedIndexStrInOrder(this.multipleSelected)
                return { examMissedClickResult, examMissedStampResult, multipleSelectedInOrder }
            },
            onCancelDialog() {
                if (this.formActions.cancel) {
                    this.formActions.cancel(this.form, this.mode)
                }
            },
            changeBackupResourcesClass(classIds) {
                console.log('changeBackupResourcesClass', classIds)
                this.getMaterialImages({
                    classIds
                })
            },
            imageListNameSelect(viewName) {
                this.imageListName = viewName
            },
            selectImage(image) {
                // 所有凭证底图，使用的图章或签名记录
                if (!this.evidenStampImages[image.id]) {
                    const { id, name, originFileName } = image
                    this.evidenStampImages[image.id] = { id, name, originFileName, stamps: [] }
                }
                // 图章或签名是否显示的标记map
                if (!this.examUsingStampImages[image.id]) {
                    this.examUsingStampImages[image.id] = {}
                }
                // 当前凭证底图使用的图章或签名
                this.usingStampImages = this.evidenStampImages[image.id].stamps
                if (!this.currentImage || this.currentImage.id !== image.id) {
                    this.currentImage = image
                    this.imageLoading = true
                }

                // 如果是考试模式并且action为select，记录选择底图
                if (
                    this.editorMode === 'exam' &&
                    (this.editorAction === 'select' || this.editorAction === 'confirm')
                ) {
                    Vue.set(this.multipleSelected, image.id, !this.multipleSelected[image.id])
                }
            },
            imageLoaded() {
                this.updateImageSize()
            },
            removeImage(imageId) {
                this.removeEvidenceImage({ fileId: imageId, ownerId: this.fileParams.ownerId })
            },
            imageBeforeUpload(res) {
                if (this.evidenceImages) {
                    for (let image of this.evidenceImages) {
                        if (res.name === image.originFileName) {
                            MessageBox.confirm('文件上传重复', '错误', {
                                confirmButtonText: '关闭',
                                type: 'error',
                                showCancelButton: false
                            })
                            return false
                        }
                    }
                }
                return true
            },
            imageUploadSuccess(res, file, fileList) {
                this.getEvidenceImages(this.fileParams.ownerId)
            },
            handleDrop(data, e) {
                this.dropOver = false
                if (this.editorMode === 'edit') {
                    // 保存加盖图章或签名位置和关联信息
                    const drapImage = {
                        ...data,
                        scaleW: 100 / this.imageWidth,
                        scaleH: 100 / this.imageHeight,
                        scaleX: (e.offsetX - 50) / this.imageWidth,
                        scaleY: (e.offsetY - 50) / this.imageHeight,
                        key: data.id + ':' + this.usingStampImages.length
                    }
                    this.usingStampImages.push(drapImage)
                } else if (
                    data &&
                    this.editorMode === 'exam' &&
                    e.target.className.indexOf('exam-area') >= 0
                ) {
                    // 测验时保存学员添加的图章或签名信息
                    let currentExamStampImages = this.examUsingStampImages[this.currentImage.id]
                    const imageKey = e.target.attributes['imagekey'].value
                    const imageId = e.target.attributes['imageid'].value
                    currentExamStampImages[imageKey] = imageId === data.id
                }
            },
            changePosition(event, image) {
                image.scaleX = event.left / this.imageWidth
                image.scaleY = event.top / this.imageHeight
                this.setActive(image, true)
            },
            changeSize(event, image) {
                image.scaleW = event.width / this.imageWidth
                image.scaleH = event.height / this.imageHeight
            },
            setActive(stampImage, active) {
                if (this.editorMode === 'edit') {
                    if (active) {
                        this.currentStampX = Math.round(stampImage.scaleX * this.imageWidth)
                        this.currentStampY = Math.round(stampImage.scaleY * this.imageHeight)
                        this.currentStampW = Math.round(stampImage.scaleW * this.imageWidth)
                        this.currentStampH = Math.round(stampImage.scaleH * this.imageHeight)
                    }
                    Vue.set(this, 'currentStamp', stampImage)
                }
            },
            updateImageSize() {
                if (document.getElementById('currentImageId')) {
                    const currentImageById = document.getElementById('currentImageId')
                    if (this.imageHeight !== currentImageById.clientHeight)
                        Vue.set(this, 'imageHeight', currentImageById.clientHeight)
                    if (this.imageWidth !== currentImageById.clientWidth)
                        Vue.set(this, 'imageWidth', currentImageById.clientWidth)
                }
                Vue.set(this, 'imageLoading', false)
            },
            getSelectedIndexStrInOrder(multipleSelected) {
                const evidenceImages = this.evidenceImages
                let multiIndexes = ''
                multipleSelected &&
                    evidenceImages &&
                    evidenceImages.map((image, index) => {
                        if (multipleSelected[image.id]) {
                            if (multiIndexes.length > 0) multiIndexes += ','
                            multiIndexes += index
                        }
                    })
                return multiIndexes
            }
        }
    }
</script>
<style lang="less">
@import '../style.less';
.evidence-editor {
    .small-dialog {
        max-height: calc(100% - 30vh);
        overflow: auto;
        margin-top: 15vh;
    }
    .exam-area {
        background-color: rgba(204, 204, 204, 0.6);
    }
    .el-dialog.is-fullscreen {
        width: 70% !important;
    }
    .el-input__inner {
        width: 100%;
    }
    .el-dialog__body {
        padding-top: 5px !important;
        padding-bottom: 5px !important;
        height: calc(100% - 70px);
    }
    .dialog-content {
        height: calc(100% - 60px);
        width: 100%;
        overflow: hidden;
        // max-height: 600px;
        .left-image-side {
            width: 180px;
        }
        .right-image-side {
            width: 200px;
        }
        .center-content {
            width: calc(100% - 380px);
            text-align: center;
        }
        .center-content-readonly {
            width: calc(100% - 200px);
            text-align: center;
        }
        .image-parent {
            position: relative;
            width: 100%;
            height: 100%;
        }
        .drag {
            height: 100%;
        }
        .drop {
            display: inline-block;
            position: relative;
            width: 100%;
            max-width: 900px;
            min-width: 400px;
        }
        .el-row {
            height: 100%;
            display: flex;
            .el-col {
                height: 100%;
                .grid-content {
                    height: 100%;
                    overflow: auto;
                    text-align: center;
                    .res-view {
                        padding: 10px 10px 0px 10px;
                        .toolbar-input-suffix {
                            margin-bottom: 15px;
                        }
                    }
                }
                .image-list-exam {
                    height: 100% !important;
                }
                .image-list {
                    height: calc(100% - 145px);
                    overflow-y: auto;
                    .image-item-active {
                        border: 2px solid var(--global-hight-color) !important;
                    }
                    .image-checked {
                        cursor: pointer;
                        display: block;
                        position: absolute;
                        font-size: 16px;
                        right: 5px;
                        top: 5px;
                        font-weight: 900;
                        color: var(--global-color);
                    }
                    .no-image-item {
                        position: relative;
                        margin: 10px;
                        z-index: 0;
                        background-color: #fff;
                        border-radius: 6px;
                        box-sizing: border-box;
                        height: 100px;
                        .no-img {
                            color: #d0d0d0;
                            padding-top: 8px;
                            font-size: 60px;
                        }
                    }
                    .image-item {
                        position: relative;
                        margin: 10px;
                        overflow: hidden;
                        z-index: 0;
                        background-color: #fff;
                        border-radius: 6px;
                        box-sizing: border-box;
                        height: 100px;
                        border: 4px solid white;
                        transition: background-color 0.5s;
                        -moz-transition: background-color 0.5s; /* Firefox 4 */
                        -webkit-transition: background-color 0.5s; /* Safari 和 Chrome */
                        -o-transition: background-color 0.5s; /* Opera */
                        img {
                            cursor: pointer;
                        }
                        .image-remove {
                            cursor: pointer;
                            display: block;
                            position: absolute;
                            font-size: 16px;
                            right: 5px;
                            top: 5px;
                            font-weight: 900;
                            color: var(--global-color);
                        }
                    }
                    .image-item-edit:hover {
                        color: var(--global-hight-color);
                        background-color: var(--global-hight-color);
                    }
                }
            }
        }
        .el-upload {
            width: 100%;
        }
        .el-upload-dragger {
            height: 120px;
            width: 100%;

            .el-icon-upload {
                font-size: 42px;
                margin: 10px;
            }
        }
    }
    .dialog-footer {
        text-align: center;
        padding-top: 15px;
        padding-bottom: 15px;
    }

    .el-row {
        margin-bottom: 20px;
        &:last-child {
            margin-bottom: 0;
        }
    }
    .el-col {
        border-radius: 4px;
    }
    .bg-purple {
        background: #f3f3f3;
    }
    .grid-content {
        border-radius: 4px;
        min-height: 36px;
    }
    .row-bg {
        padding: 10px 0;
        background-color: #f9fafc;
    }
}
</style>
